/* eslint-disable no-use-before-define */
import { defineComponent, ref, watch, onMounted, withModifiers, SetupContext } from 'vue';
import { Color } from '../class/color.class';
import './scss/hue.scss';
import { hueProps, HueProps } from './props/hue.props';

export default defineComponent({
    name: 'Hue',
    props: hueProps,
    emits: ['update:color', 'update:hue'] as (string[] & ThisType<void>) | undefined,
    setup(props: HueProps, context: SetupContext) {
        const hueRef = ref(props.hue);
        const allowColorNull = ref(props.allowColorNull);
        // 注册事件并清空待注册列表
        const eventHooks: (() => void)[] = [];
        function calculate(event: MouseEvent | TouchEvent): void {
            event.preventDefault();
            calculateCoordinates(event);
        }
        const elementRef = ref<HTMLDivElement | null>(null);
        function calculateCoordinates(event: MouseEvent | TouchEvent): void {
            if (elementRef.value) {
                const { width: elWidth, height: elHeight, top: elTop, left: elLeft } = elementRef.value.getBoundingClientRect();

                const { pageX, pageY } = 'touches' in event ? event.touches[0] : event;

                const x = Math.max(0, Math.min(pageX - (elLeft + window.pageXOffset), elWidth));
                const y = Math.max(0, Math.min(pageY - (elTop + window.pageYOffset), elHeight));

                movePointer({ x, y, height: elHeight, width: elWidth });
            }
        }
        function removeListeners(): void {
            eventHooks.forEach((cb) => cb());
            eventHooks.length = 0;
        }
        function onEventChange(event: MouseEvent | TouchEvent): void {
            calculate(event);
            document.addEventListener('mouseup', removeListeners);
            document.addEventListener('touchend', removeListeners);
            document.addEventListener('touchmove', calculate);
        }

        const handleOnClick = (event: any) => {
            onEventChange(event);
        };

        onMounted(() => {
            const targetElements = document.querySelectorAll('.f-hue-component');
            targetElements.forEach((element) => {
                element.addEventListener('mousedown', handleOnClick);
                element.addEventListener('touchstart', handleOnClick);
            });
            const hsva = props.color.getHsva();
            changePointerPosition(hsva.hue);
        });

        const thumbRef = ref<HTMLDivElement | null>(null);

        function changePointerPosition(hue: number): void {
            const x = Math.max(0, Math.min((hue / 360) * 100, 100));
            const orientation = 'top';
            if (thumbRef.value) {
                const thumbRefValue = thumbRef.value;
                thumbRefValue.style?.setProperty(orientation, `${x}%`);
            }
        }

        class clickValue {
            x = 0;

            y = 0;

            height = 0;

            width = 0;
        }

        function movePointer({ x, y, height, width }: clickValue): void {
            const hue = (y / height) * 360;
            changePointerPosition(hue);

            const color = props.color.getHsva();
            const newColor = new Color().setHsva(hue, color.saturation, color.value, color.alpha);
            const newHueColor = new Color().setHsva(hue, 100, 100, color.alpha);

            if (props.color != null) {
                context.emit('update:hue', newHueColor);
                context.emit('update:color', newColor);
            } else if (props.color == null && allowColorNull.value) {
                context.emit('update:hue', newHueColor);
                context.emit('update:color', newColor);
            }
        }
        watch(hueRef, (newValue) => {
            const hsva = newValue.getHsva();
            changePointerPosition(hsva.hue);
        });
        watch(
            () => props.color,
            (newValue) => {
                const hsva = newValue.getHsva();
                changePointerPosition(hsva.hue);
            }
        );
        return () => (
            <div
                class="f-hue-component"
                ref={elementRef}
                onMousedown={withModifiers((payload: MouseEvent) => calculateCoordinates(payload), ['prevent'])}
                onTouchstart={withModifiers((payload: TouchEvent) => calculateCoordinates(payload), ['prevent'])}>
                <div class="color-hue-slider__bar"></div>
                <div class="color-hue-slider__thumb" ref={thumbRef}></div>
            </div>
        );
    }
});
